package fudan.se.project.service.infrastructure.entity.conference.production;


import fudan.se.project.domain.User;
import fudan.se.project.domain.conference.Conference;
import fudan.se.project.domain.conference.production.Paper;
import fudan.se.project.repository.entity.conference.production.PaperRepository;
import fudan.se.project.service.infrastructure.base.IEntityService;
import fudan.se.project.service.infrastructure.base.StorageService;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.core.io.InputStreamResource;
import org.springframework.stereotype.Service;
import org.springframework.web.multipart.MultipartFile;

import java.util.Collection;
import java.util.List;


@Slf4j
@Service
public class PaperService implements IEntityService<Paper> {

    private final StorageService storageService;
    private final PaperRepository paperRepository;
    private static final String CONFERENCE="/conference/";
    private static final String PAPER="/paper/";

    @Autowired
    public PaperService(StorageService storageService, PaperRepository paperRepository) {
        this.storageService = storageService;
        this.paperRepository = paperRepository;
    }


    @Override
    public Paper findById(long id) {
        return paperRepository.findById(id);
    }

    @Override
    public Paper save(Paper paper) {
        return paperRepository.save(paper);
    }

    public void deletePaperEntity(Paper paper) {
        this.paperRepository.delete(paper);
    }


    @Override
    public Iterable<Paper> saveAll(Collection<Paper> papers) {
        return paperRepository.saveAll(papers);
    }

    /**
     * Stores the file to disk.
     *
     * @return true if stored successfully; false failed.
     */
    public boolean store(long conferenceId, long paperId, MultipartFile file) {
        return storageService.store(file, CONFERENCE + conferenceId + PAPER
                + paperId + "/" + file.getOriginalFilename());
    }


    public boolean deletePaperFile(Paper paper) {
        return storageService.delete(CONFERENCE + paper.getConference().getId()
                + PAPER + +paper.getId() + "/" + paper.getOriginalFilename());
    }

    public InputStreamResource downLoad(Paper paper) {
        if (paper == null) return null;
        return storageService.downLoad(CONFERENCE + paper.getConference().getId()
                + PAPER + +paper.getId() + "/" + paper.getOriginalFilename());
    }


    public List<Paper> findUnrebuttedForAuthor(long conferenceId, User author) {
        return paperRepository.findUnrebuttedByConferenceIdAndAuthor(conferenceId, author);
    }

    public List<Paper> findPapersForReviewers(User reviewer, Conference conference, boolean isCompleted) {
        return paperRepository.findByReviewerAndReviewStateInConference(reviewer, conference, isCompleted);
    }

    public List<Paper> findUnconfirmedPapers(long conferenceId, int version) {
        return paperRepository.findUnconfirmedFromReviewersByReviewVersion(conferenceId, version);
    }

    public List<Paper> findUnconfirmedRebuttedPapers(long conferenceId, int version) {
        return paperRepository.findRebuttedPapersInConference(conferenceId, version);
    }

    public List<Paper> findRebuttedPapers(long conferenceId, User reviewer, boolean confirmed) {
        final int version = confirmed ? 2 : 1;
        return paperRepository.
                findRebuttedPapersInConference(conferenceId, reviewer, version);
    }
}
